package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.itheima.dubbo.api.CommentsApi;
import com.itheima.dubbo.api.MovementsApi;
import com.itheima.dubbo.api.UserInfoApi;
import com.itheima.dubbo.api.VisitorsApi;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongoDb.Comment;
import com.tanhua.model.mongoDb.Movement;
import com.tanhua.model.mongoDb.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserThreadLocal;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author Pan Rundong
 * @Date 2023-02-28 23:59
 * @Desc 动态Service
 */
@Service
public class MovementsService {
    @DubboReference
    private MovementsApi movementsApi;
    @Autowired
    private OssTemplate ossTemplate;
    @DubboReference(version = "1.0.0")
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @DubboReference
    private CommentsApi commentsApi;
    @DubboReference
    private VisitorsApi visitorsApi;

    /**
     * 发布动态
     *
     * @param movement
     * @param imageContent
     * @return void
     * @Author Pan Rundong
     */
    public void publicMovements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //0.判断当前内容是否存在
        if (movement.getTextContent() == null) {
            throw new BusinessException(ErrorResult.contentError());
        }

        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();

        //2.上传阿里云，获取地址
        List<String> urlList = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            urlList.add(upload);
        }

        //3.保存地址进movement
        movement.setUserId(userId);
        movement.setMedias(urlList);

        //4.调用远程Api保存动态
        movementsApi.publicMovements(movement);
    }

    /**
     * 查看动态
     *
     * @param page
     * @param pagesize
     * @param userId
     * @return com.tanhua.model.vo.PageResult
     * @Author Pan Rundong
     */
    public PageResult all(Integer page, Integer pagesize, Long userId) {
        //1.远程调用
        PageResult pageResult = movementsApi.findById(page, pagesize, userId);

        //2.获取itemList
        List<Movement> list = (List<Movement>) pageResult.getItems();
        //3.判断是否为空
        if (list == null || list.size() == 0) {
            return pageResult;
        }

        //4.获取userInfo
        UserInfo userInfo = userInfoApi.findById(userId);

        //5.创建voList
        List<MovementsVo> voList = list.stream().map(movement -> {
            //5.1 创建对象
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //5.2 返回
            return vo;
        }).collect(Collectors.toList());

        //6.将voList存入pageResult
        pageResult.setItems(voList);

        //7.返回
        return pageResult;
    }

    /**
     * 查看好友动态
     *
     * @param page
     * @param pagesize
     * @return com.tanhua.model.vo.PageResult
     * @Author Pan Rundong
     */
    public PageResult friendsMovements(Integer page, Integer pagesize) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();

        //2.调用api查询好友动态
        PageResult pageResult = movementsApi.friendsMovements(page, pagesize, userId);

        //3.调用公共类封装Vo
        pageResult = getMovementsVo(pageResult);

        //4.返回分页信息
        return pageResult;
    }

    /**
     * 查询动态 --- 公共方法
     *
     * @param pageResult
     * @return com.tanhua.model.vo.PageResult
     * @Author Pan Rundong
     */
    private PageResult getMovementsVo(PageResult pageResult) {
        //2.获取itemList
        List<Movement> list = (List<Movement>) pageResult.getItems();
        //3.判断是否为空
        if (list == null || list.size() == 0) {
            return pageResult;
        }
        //4、提取动态发布人的id列表
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);

        //5.获取userInfo
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, null);

        //6.创建voList
        List<MovementsVo> voList = list.stream().map(movement -> {
            //5.1 创建对象
            MovementsVo vo = MovementsVo.init(userInfoMap.
                    get(movement.getUserId()), movement);
            //5.2 查看点赞状态
            String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + movement.getUserId();
            if (redisTemplate.opsForHash().hasKey(key, hashKey)) {
                vo.setHasLiked(1);
            }
            //5.2 返回
            return vo;
        }).collect(Collectors.toList());

        //6.将voList存入pageResult
        pageResult.setItems(voList);
        pageResult.setCounts(0);

        //7.返回
        return pageResult;
    }

    /**
     * 推荐动态
     *
     * @param page
     * @param pagesize
     * @return com.tanhua.model.vo.PageResult
     * @Author Pan Rundong
     */
    public PageResult recommend(Integer page, Integer pagesize) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();

        //2.从Redis中获取推荐动态Pid
        String key = Constants.MOVEMENTS_RECOMMEND + userId;
        String pidsStr = redisTemplate.opsForValue().get(key);


        //3.判断是否存在推荐动态
        PageResult pageRecommend = null;
        if (pidsStr == null || pidsStr == "") {
            //3.1 不存在，调用Api随机获取10条动态
            pageRecommend = movementsApi.randomRecommend(pagesize);
        } else {
            //3.2 存在，调用Api分页查询
            String[] values = pidsStr.split(",");
            if ((page - 1) * pagesize < values.length) {
                List<Long> pids = Arrays.stream(values).map(id->Long.valueOf(id))
                        .collect(Collectors.toList());
                pageRecommend = movementsApi.recommend(page, pagesize, pids);
            }
        }

        //4.调用公用方法获取分页信息
        pageRecommend = getMovementsVo(pageRecommend);

        //5.返回
        return pageRecommend;
    }

    /**
     * 根据动态Id查询动态
     *
     * @param id
     * @return com.tanhua.model.vo.MovementsVo
     * @Author Pan Rundong
     */
        public MovementsVo getById(String id) {
        //1.查询动态
        Movement movement = movementsApi.getById(id);

        //2.判断动态是否存在
        if (movement != null) {
            //3.1 存在，获取对应用户信息，封装vo并返回
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //3.2 返回
            return vo;
        } else {
            return null;
        }
    }

    /**
     * 动态点赞
     *
     * @param movementId
     * @return java.lang.Integer
     * @Author Pan Rundong
     */
    public Integer like(String movementId) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();
        //2.查询用户是否已经点赞
        Boolean flag = movementsApi.haveOrNot(movementId, CommentType.LIKE, userId);

        //3.判断点赞状态
        if (flag) {
            //已点赞，抛出异常
            throw new BusinessException(ErrorResult.likeError());
        }

            //未点赞
        //4.保存评论信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userId);
        comment.setCommentType(CommentType.LIKE.getType());

        //5.调用Api保存点赞信息
        int count = commentsApi.publish(comment);

        //6.设置Reids的Key与value
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;

        //7.保存点赞信息至Redis
        redisTemplate.opsForHash().put(key, hashKey,"1");
        //8.返回总点赞数
        return count;
    }

    /**
     * 取消点赞
     *
     * @param movementId
     * @return java.lang.Integer
     * @Author Pan Rundong
     */
    public Integer disLike(String movementId) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();
        //2.查询用户是否已经点赞
        Boolean flag = movementsApi.haveOrNot(movementId, CommentType.LIKE, userId);

        //3.判断点赞状态
        if (flag) {
            //未点赞，抛出异常
            throw new BusinessException(ErrorResult.likeError());
        }

        //已点赞
        //4.保存评论信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userId);
        comment.setCommentType(CommentType.LIKE.getType());

        //5.调用Api保存点赞信息
        int count = commentsApi.delete(comment);

        //6.设置Reids的Key与value
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;

        //7.保存点赞信息至Redis
        redisTemplate.opsForHash().delete(key, hashKey,"1");
        //8.返回总点赞数
        return count;
    }

    /**
     * 动态喜欢
     *
     * @param movementId
     * @return java.lang.Integer
     * @Author Pan Rundong
     */
    public Integer love(String movementId) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();
        //2.查询用户是否已经喜欢
        Boolean flag = movementsApi.haveOrNot(movementId, CommentType.LOVE, userId);

        //3.判断喜欢状态
        if (flag) {
            //已喜欢，抛出异常
            throw new BusinessException(ErrorResult.likeError());
        }

        //未喜欢
        //4.保存评论信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userId);
        comment.setCommentType(CommentType.LOVE.getType());

        //5.调用Api保存喜欢信息
        int count = commentsApi.publish(comment);

        //6.设置Reids的Key与value
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + userId;

        //7.保存喜欢信息至Redis
        redisTemplate.opsForHash().put(key, hashKey,"1");
        //8.返回总点赞数
        return count;
    }

    /**
     * 取消喜欢
     *
     * @param movementId
     * @return java.lang.Integer
     * @Author Pan Rundong
     */
    public Integer unLove(String movementId) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();
        //2.查询用户是否已经喜欢
        Boolean flag = movementsApi.haveOrNot(movementId, CommentType.LOVE, userId);

        //3.判断喜欢状态
        if (flag) {
            //未喜欢，抛出异常
            throw new BusinessException(ErrorResult.likeError());
        }

        //已喜欢
        //4.保存评论信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(userId);
        comment.setCommentType(CommentType.LOVE.getType());

        //5.调用Api保存点赞信息
        int count = commentsApi.delete(comment);

        //6.设置Reids的Key与value
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + userId;

        //7.保存喜欢信息至Redis
        redisTemplate.opsForHash().delete(key, hashKey,"1");
        //8.返回总喜欢数
        return count;
    }

    /**
     * 谁看过我
     *
     * @param
     * @return java.util.List<com.tanhua.model.vo.VisitorsVo>
     * @Author Pan Rundong
     */
    public List<VisitorsVo> visitors() {
        //1.获取用户Id以及访问时间
        Long userId = UserThreadLocal.getUserId();
        String key = Constants.VISITORS_USER;
        String hashKey = String.valueOf(userId);
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(value) ? null:Long.valueOf(value);

        //2.调用Api获取看过用户
        List<Visitors> list = visitorsApi.visitors(date, userId);

        //3.获取看过用户Id，调用Api获取用户信息
        List<Long> ids = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(ids, null);

        //4.封装Vo
        List<VisitorsVo> voList = new ArrayList<>();
        for (Visitors visitor : list) {
            UserInfo userInfo = userInfoMap.get(visitor.getUserId());
            if (userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo, visitor);
                voList.add(vo);
            }
        }

        //5.返回数据
        return voList;
    }
}
